package com.yueyang.sojourn.server.common.baymax.web.result;

import com.yueyang.sojourn.server.common.baymax.web.result.exception.*;

/**
 * 常用的一些断言，不满足断言条件将抛出一些内置的运行时异常，可以指定业务错误码和业务提示消息。<br>
 * 如果不指定业务错误码，系统默认返回 {@link ResultCode#UNKNOWN}。<br>
 * 我们会自动将异常转换为标准错误输出（异常对应的Http 状态码详见方法说明）：
 * 
 * <pre>
 * {
 *   "code": 102002, //业务错误码
 *   "message": "您的工号已被锁定", //错误相关的提示信息
 *   "timestamp": 10234444444L, //请求时间戳
 *   "path":"/v1/user/1",  //请求路径
 * }
 * </pre>
 * 
 * 如果常见断言不满足业务，各系统可继承 {@link StandardBusinessException}，可直接抛出。例如：
 * 
 * <pre>
 * public class MyBussinessException extends StandardBusinessException {
 *   public MyBussinessException() {
 *     super(102000, "标准错误信息", HttpStatus.FORBIDDEN);
 *   }
 * }
 * </pre>
 * 
 * 但是我们推荐各个业务系统自定义一系列： {@link RestResult}，比如：
 * 
 * 普通SpringMVC项目或者Spring Boot项目
 * 
 * <pre>
 * public interface AppRestResult {
 *   RestResult ERROR_ALREADY_APPLIED = new StandardRestResult(10003, "XXX已申请");
 * }
 * </pre>
 * 
 * SPI 接口可以使用BizCode，系统会自动适配成RestResult
 * 
 * <pre>
 * public interface AppBizCode {
 *   BizCode ERROR_ALREADY_APPLIED = new BizCode(10003, "XXX已申请");
 * }
 * </pre>
 * 
 * 调用示例：
 * 
 * <pre>
 * {@code @Service }
 * public class MyService{
 *    public boolean apply(int userCode){
 *       //一些逻辑
 *       ApplyInfo apply=applyInfoDao.findByUserCode(userCode);
 *       JAssert.pass(apply == null,AppRestResult.ERROR_AREADY_APPLIED);
 *       //其他逻辑
 *    }
 * }
 * </pre>
 * 
 * @author huisman
 * @Copyright (c) 2015, yueyang Group All Rights Reserved.
 */
public abstract class JAssert {

  private JAssert() {
    new AssertionError("no");
  }

  /**
   * 判定记录expression=true ,如果expression=false，则抛出 {@link NotFoundException} ，对应http status: 404
   * 
   * @since 1.0.0
   * @param expression
   * @param bizCode 业务码信息，不能为null
   */
  public static void found(boolean expression, Object bizCode) {
    if (!expression) {
      justNotFound(bizCode);
    }
  }

  /**
   * 判定记录expression=true ,如果expression=false，则抛出 {@link NotFoundException} ，对应http status: 404
   * 
   * @since 1.0.0
   * @param expression
   * @param bizCode 业务码信息，不能为null
   * @param onAssertFailed 当断言失败时，抛出异常之前执行的回调函数
   */
  public static void found(boolean expression, Object bizCode, OnAssertFailed onAssertFailed) {
    if (!expression) {
      if (onAssertFailed != null) {
        onAssertFailed.callback();
      }
      justNotFound(bizCode);
    }
  }

  /**
   * <p>
   * 记录不存在，异常对应的Http 状态码：404<br>
   * 直接抛出{@link NotFoundException}，指定错误信息。
   * </p>
   * 
   * @since 1.0.0
   * @param message 业务提示信息
   */
  public static void justNotFound(String message) {
    throw new NotFoundException(message);
  }

  /**
   * <p>
   * 记录不存在，异常对应的Http 状态码：404<br>
   * 直接抛出{@link NotFoundException},可以指定业务系统的错误码和提示消息
   * </p>
   * 
   * @since 1.0.0
   * @param errorCode 业务错误码
   * @param message 业务提示信息
   */
  public static void justNotFound(int errorCode, String message) {
    throw new NotFoundException(errorCode, message);
  }

  /**
   * <p>
   * 记录是否存在，异常对应的Http 状态码：404<br>
   * expression 为false时抛出{@link NotFoundException}，指定错误信息。
   * </p>
   * 
   * @since 1.0.0
   * @param expression 业务boolean 表达式
   * @param message 业务提示信息
   */
  public static void found(boolean expression, String message) {
    if (!expression) {
      justNotFound(message);
    }
  }

  /**
   * <p>
   * 判定记录expression=true <br>
   * 如果expression=false时抛出{@link NotFoundException}，
   * 异常对应的Http 状态码：404,可以指定业务系统的错误码和提示消息。
   * </p>
   * 
   * @since 1.0.0
   * @param expression
   * @param errorCode 业务错误码
   * @param message 业务提示信息
   */
  public static void found(boolean expression, int errorCode, String message,
      OnAssertFailed onAssertFailed) {
    if (!expression) {
      if (onAssertFailed != null) {
        onAssertFailed.callback();
      }
      justNotFound(errorCode, message);
    }
  }

  /**
   * <p>
   * 判定记录expression=true <br>
   * 如果expression=false时抛出{@link NotFoundException}，
   * 异常对应的Http 状态码：404,可以指定业务系统的错误码和提示消息。
   * </p>
   * 
   * @since 1.0.0
   * @param expression
   * @param errorCode 业务错误码
   * @param message 业务提示信息
   */
  public static void found(boolean expression, int errorCode, String message) {
    if (!expression) {
      justNotFound(errorCode, message);
    }
  }

  /**
   * 直接抛出 {@link NotFoundException}，对应的Http 状态码：404，同时将输出 {@code RestResult}
   * 
   * @param bizCode 业务码信息
   */
  public static void justNotFound(Object bizCode) {
    RestResult result = RestResultProviders.getRestResult(bizCode);
    justNotFound(result.getCode(), result.getMessage());
  }


  /**
   * <p>
   * 参数是否非法，异常对应的Http 状态码：400<br>
   * expression为false时抛出{@link InvalidParameterException},可以指定业务系统的错误码和提示消息.
   * </p>
   * 
   * @since 1.0.0
   * @param expression
   * @param errorCode 业务错误码
   * @param message 业务提示信息
   */
  public static void validParam(boolean expression, int errorCode, String message,
      OnAssertFailed onAssertFailed) {
    if (!expression) {
      if (onAssertFailed != null) {
        onAssertFailed.callback();
      }
      justInvalidParam(errorCode, message);
    }
  }


  /**
   * <p>
   * 参数是否非法，异常对应的Http 状态码：400<br>
   * expression为false时抛出{@link InvalidParameterException},可以指定业务系统的错误码和提示消息.
   * </p>
   * 
   * @since 1.0.0
   * @param expression
   * @param errorCode 业务错误码
   * @param message 业务提示信息
   */
  public static void validParam(boolean expression, int errorCode, String message) {
    if (!expression) {
      justInvalidParam(errorCode, message);
    }
  }

  /**
   * <p>
   * 参数是否非法，异常对应的Http 状态码：400<br>
   * expression 为false时抛出{@link InvalidParameterException},可以指定业务提示消息。
   * </p>
   * 
   * @since 1.0.0
   * @param expression
   * @param message 业务提示信息
   */
  public static void validParam(boolean expression, String message) {
    if (!expression) {
      justInvalidParam(message);
    }
  }


  /**
   * 参数是否异常，如果false，则抛出 {@link InvalidParameterException}，对应 http status : 400
   * 
   * @since 1.0.0
   * @param expression
   * @param bizCode 业务码信息
   * @param onAssertFailed 当断言失败时，抛出异常之前执行的回调函数
   */
  public static void validParam(boolean expression, Object bizCode, OnAssertFailed onAssertFailed) {
    if (!expression) {
      if (onAssertFailed != null) {
        onAssertFailed.callback();
      }
      justInvalidParam(bizCode);
    }
  }

  /**
   * 参数是否异常，如果false，则抛出 {@link InvalidParameterException}，对应 http status : 400
   * 
   * @since 1.0.0
   * @param expression
   * @param bizCode 业务码信息
   */
  public static void validParam(boolean expression, Object bizCode) {
    if (!expression) {
      justInvalidParam(bizCode);
    }
  }

  /**
   * 直接抛出参数异常，对应Http 状态码： 400
   * 
   * @since 1.0.0
   * @param errorCode 业务错误码
   * @param message 业务提示信息
   */
  public static void justInvalidParam(int errorCode, String message) {
    throw new InvalidParameterException(errorCode, message);
  }

  /**
   * 直接抛出业务异常，对应Http 状态码： 400
   * 
   * @since 1.0.0
   * @param message 业务提示信息
   */
  public static void justInvalidParam(String message) {
    throw new InvalidParameterException(message);
  }

  /**
   * 直接抛出非法参数异常，对应的Http 状态码：400，同时将输出 {@code RestResult}
   * 
   * @param bizCode 业务码信息
   */
  public static void justInvalidParam(Object bizCode) {
    RestResult restResult = RestResultProviders.getRestResult(bizCode);
    justInvalidParam(restResult.getCode(), restResult.getMessage());
  }


  /**
   * <p>
   * 是否允许访问，异常对应的Http 状态码：403<br>
   * expression 为false时抛出{@link AccessDeniedException},可以指定业务系统提示消息
   * </p>
   * 
   * @since 1.0.0
   * @param expression
   * @param message 业务提示信息
   */
  public static void allowed(boolean expression, String message) {
    if (!expression) {
      justDenied(message);
    }
  }

  /**
   * <p>
   * 是否允许访问，异常对应的Http 状态码：403<br>
   * expression 为false时抛出{@link AccessDeniedException},可以指定业务系统的错误码和提示消息
   * </p>
   * 
   * @since 1.0.0
   * @param expression
   * @param message 业务提示信息
   */
  public static void allowed(boolean expression, int errorCode, String message,
      OnAssertFailed onAssertFailed) {
    if (!expression) {
      if (onAssertFailed != null) {
        onAssertFailed.callback();
      }
      justDenied(errorCode, message);
    }
  }

  /**
   * <p>
   * 是否允许访问，异常对应的Http 状态码：403<br>
   * expression 为false时抛出{@link AccessDeniedException},可以指定业务系统的错误码和提示消息
   * </p>
   * 
   * @since 1.0.0
   * @param expression
   * @param message 业务提示信息
   */
  public static void allowed(boolean expression, int errorCode, String message) {
    if (!expression) {
      justDenied(errorCode, message);
    }
  }

  /**
   * 是否允许访问，如果 expression = false ,则不允许访问，对应Http 状态码为： 403;
   * 
   * @since 1.0.0
   * @param expression
   * @param bizcode 业务码信息
   */
  public static void allowed(boolean expression, Object bizcode) {
    if (!expression) {
      justDenied(bizcode);
    }
  }

  /**
   * 是否允许访问，如果 expression = false ,则不允许访问，对应Http 状态码为： 403;
   * 
   * @since 1.0.0
   * @param expression
   * @param bizcode 业务码信息
   * @param onAssertFailed 当断言失败时，抛出异常之前执行的回调函数
   */
  public static void allowed(boolean expression, Object bizcode, OnAssertFailed onAssertFailed) {
    if (!expression) {
      if (onAssertFailed != null) {
        onAssertFailed.callback();
      }
      justDenied(bizcode);
    }
  }

  /**
   * 直接抛出访问被拒绝，对应Http 状态码： 403
   * 
   * @since 1.0.0
   * @param errorCode 业务错误码
   * @param message 业务提示信息
   */
  public static void justDenied(int errorCode, String message) {
    throw new AccessDeniedException(errorCode, message);
  }

  /**
   * 直接抛出访问被拒绝异常，对应Http 状态码： 403
   * 
   * @since 1.0.0
   * @param message 业务提示信息
   */
  public static void justDenied(String message) {
    throw new AccessDeniedException(message);
  }

  /**
   * 直接抛出访问被拒绝异常，对应的Http 状态码：403，同时将输出 {@code RestResult}
   * 
   * @since 1.0.0
   */
  public static void justDenied(Object bizCode) {
    RestResult result = RestResultProviders.getRestResult(bizCode);
    justDenied(result.getCode(), result.getMessage());
  }

  /**
   * <p>
   * 是否已授权，异常对应的Http 状态码：401<br>
   * expression 为false时抛出{@link UnauthorizedException}，指定错误信息。
   * </p>
   * 
   * @since 1.0.0
   * @param expression
   * @param message 业务提示信息
   */
  public static void authorized(boolean expression, String message) {
    if (!expression) {
      justUnauthorized(message);
    }
  }

  /**
   * <p>
   * 是否已授权，异常对应的Http 状态码：401<br>
   * expression 为false时抛出{@link UnauthorizedException},可以指定业务系统的错误码和提示消息
   * </p>
   * 
   * @since 1.0.0
   * @param expression
   * @param errorCode 业务错误码
   * @param message 业务提示信息
   */
  public static void authorized(boolean expression, int errorCode, String message,
      OnAssertFailed onAssertFailed) {
    if (!expression) {
      if (onAssertFailed != null) {
        onAssertFailed.callback();
      }
      justUnauthorized(errorCode, message);
    }
  }

  /**
   * <p>
   * 是否已授权，异常对应的Http 状态码：401<br>
   * expression 为false时抛出{@link UnauthorizedException},可以指定业务系统的错误码和提示消息
   * </p>
   * 
   * @since 1.0.0
   * @param expression
   * @param errorCode 业务错误码
   * @param message 业务提示信息
   */
  public static void authorized(boolean expression, int errorCode, String message) {
    if (!expression) {
      justUnauthorized(errorCode, message);
    }
  }

  /**
   * 是否授权,对应http 状态码 401，如果 expression = false ,则直接抛出异常 {@link UnauthorizedException};
   * 
   * @since 1.0.0
   * @param bizCode
   */
  public static void authorized(boolean expression, Object bizCode) {
    if (!expression) {
      justUnauthorized(bizCode);;
    }
  }

  /**
   * 是否授权,对应http 状态码 401，如果 expression = false ,则直接抛出异常 {@link UnauthorizedException};
   * 
   * @since 1.0.0
   * @param onAssertFailed 当断言失败时，抛出异常之前执行的回调函数
   */
  public static void authorized(boolean expression, Object bizCode, OnAssertFailed onAssertFailed) {
    if (!expression) {
      if (onAssertFailed != null) {
        onAssertFailed.callback();
      }
      justUnauthorized(bizCode);;
    }
  }

  /**
   * <p>
   * 业务逻辑是否正常，异常对应的Http 状态码：417<br>
   * expression 为false时抛出{@link StandardBusinessException},可以指定业务系统的错误码和提示消息
   * </p>
   * 
   * @since 1.0.0
   * @param expression
   * @param errorCode 业务错误码
   * @param message 业务提示信息
   */
  public static void pass(boolean expression, int errorCode, String message,
      OnAssertFailed onAssertFailed) {
    if (!expression) {
      if (onAssertFailed != null) {
        onAssertFailed.callback();
      }
      justFailed(errorCode, message);
    }
  }

  /**
   * <p>
   * 业务逻辑是否正常，异常对应的Http 状态码：417<br>
   * expression 为false时抛出{@link StandardBusinessException},可以指定业务系统的错误码和提示消息
   * </p>
   * 
   * @since 1.0.0
   * @param expression
   * @param errorCode 业务错误码
   * @param message 业务提示信息
   */
  public static void pass(boolean expression, int errorCode, String message) {
    if (!expression) {
      justFailed(errorCode, message);
    }
  }

  /**
   * <p>
   * 业务逻辑是否正常，异常对应的Http 状态码：417<br>
   * expression 为false时抛出{@link StandardBusinessException},可以指定业务系统提示消息
   * </p>
   * 
   * @since 1.0.0
   * @param expression
   * @param message 业务提示信息
   */
  public static void pass(boolean expression, String message) {
    if (!expression) {
      justFailed(message);
    }
  }

  /**
   * 业务逻辑是否正常，如果 expression = false ,则直接抛出异常 {@link StandardBusinessException}，对应http status:417
   * 
   * @since 1.0.0
   * @param expression
   * @param bizCode 业务码信息
   */
  public static void pass(boolean expression, Object bizCode) {
    if (!expression) {
      justFailed(bizCode);
    }
  }

  /**
   * 业务逻辑是否正常，如果 expression = false ,则直接抛出异常 {@link StandardBusinessException}，对应http status:417
   * 
   * @since 1.0.0
   * @param expression
   * @param bizCode 业务码信息
   * @param onAssertFailed 当断言失败时，抛出异常之前执行的回调函数
   */
  public static void pass(boolean expression, Object bizCode, OnAssertFailed onAssertFailed) {
    if (!expression) {
      if (onAssertFailed != null) {
        onAssertFailed.callback();
      }
      justFailed(bizCode);
    }
  }

  /**
   * 直接抛出业务失败异常，对应Http 状态码： 417
   * 
   * @since 1.0.0
   * @param errorCode 业务错误码
   * @param message 业务提示信息
   */
  public static void justFailed(int errorCode, String message) {
    throw new StandardBusinessException(errorCode, message);
  }

  /**
   * 直接抛出业务失败异常，对应Http 状态码： 417
   * 
   * @since 1.0.0
   * @param message 业务提示信息
   */
  public static void justFailed(String message) {
    throw new StandardBusinessException(message);
  }

  /**
   * 直接抛出业务异常，对应的Http 状态码：417，同时将输出 {@code RestResult}
   * 
   * @param bizcode 业务码信息
   */
  public static void justFailed(Object bizcode) {
    RestResult result = RestResultProviders.getRestResult(bizcode);
    justFailed(result.getCode(), result.getMessage());
  }

  /**
   * 未授权，异常对应的Http 状态码：401<br>
   * 直接抛出{@link UnauthorizedException}，可指定错误信息。
   * 
   * @since 1.0.0
   * @param message 业务提示信息
   */
  public static void justUnauthorized(String message) {
    throw new UnauthorizedException(message);
  }

  /**
   * 未授权，对应的Http 状态码：401<br>
   * 直接抛出{@link UnauthorizedException},可以指定业务系统的错误码和提示消息
   * 
   * @since 1.0.0
   * @param errorCode 业务错误码
   * @param message 业务提示信息
   */
  public static void justUnauthorized(int errorCode, String message) {
    throw new UnauthorizedException(errorCode, message);
  }

  /**
   * 直接抛出未授权异常，对应的Http 状态码：401，同时将输出 {@code RestResult}
   * 
   * @since 1.0.0
   * @param bizcode 业务码信息，不能为空
   */
  public static void justUnauthorized(Object bizcode) {
    RestResult result = RestResultProviders.getRestResult(bizcode);
    justUnauthorized(result.getCode(), result.getMessage());
  }
}
